package net.wicp.tams.common.others.docker;

import java.util.concurrent.CountDownLatch;

import io.fabric8.docker.client.Config;
import io.fabric8.docker.client.ConfigBuilder;
import io.fabric8.docker.client.DefaultDockerClient;
import io.fabric8.docker.client.DockerClient;
import io.fabric8.docker.dsl.EventListener;
import io.fabric8.docker.dsl.OutputHandle;
import lombok.extern.slf4j.Slf4j;
import net.wicp.tams.common.Conf;
import net.wicp.tams.common.Result;
import net.wicp.tams.common.apiext.IOUtil;

@Slf4j
public class DockerUtil {

	private static DockerUtil inst = new DockerUtil();
	private final DockerClient docker;

	public DockerClient getDocker() {
		return docker;
	}

	private DockerUtil() {
		String url = Conf.get("common.others.docker.url");
		Config config = new ConfigBuilder().withDockerUrl(url).build();
		docker = new DefaultDockerClient(config);
	}

	public static DockerUtil getInst() {
		return DockerUtil.inst;
	}

	public Result buildImage(String imageFolder, String image) {
		final Result ret = Result.getError("");
		try {
			final CountDownLatch buildDone = new CountDownLatch(1);
			OutputHandle handle = this.docker.image().build().withRepositoryName(image)
					.usingListener(new EventListener() {
						@Override
						public void onSuccess(String message) {
							log.info("成功打doccker image:{}", message);
							buildDone.countDown();
							ret.setMessage("ok");
						}

						@Override
						public void onError(String messsage) {
							log.error("Failure:" + messsage);
							buildDone.countDown();
							ret.setMessage(messsage);
						}

						@Override
						public void onError(Throwable t) {
							log.error("Failure", t);
							buildDone.countDown();
							ret.setMessage(t.getMessage());
						}

						@Override
						public void onEvent(String event) {
						}
					}).fromFolder(imageFolder);
			buildDone.await();
			handle.close();
			return "ok".equals(ret.getMessage()) ? Result.getSuc() : ret;
		} catch (Exception e) {
			log.error("build失败", e);
			ret.setMessage(e.getMessage());
			return ret;
		}
	}

	/***
	 * 推送image到repository eg:
	 * pushImage("10.100.19.136:5000/hammer","1.5-2","hammer:1"); 把image:hammer:1
	 * 推为:10.100.19.136:5000/hammer:1.5-2
	 * 
	 * @param repositoryName
	 *            注册库的名称
	 * @param tagName
	 *            注册库的tag
	 * @param image
	 *            要注册的image
	 * @return
	 */
	public Result pushImage(String image, String repositoryName, String tagName) {
		final Result ret = Result.getError("");
		try {
			final CountDownLatch pushDone = new CountDownLatch(1);
			this.docker.image().withName(image).tag().inRepository(repositoryName).force().withTagName(tagName);
			OutputHandle handle = this.docker.image().withName(repositoryName).push()
					.usingListener(new EventListener() {
						@Override
						public void onSuccess(String message) {
							log.info("push success:{}", message);
							pushDone.countDown();
							ret.setMessage("ok");
						}

						@Override
						public void onError(String messsage) {
							log.error("Failure:" + messsage);
							pushDone.countDown();
							ret.setMessage(messsage);
						}

						@Override
						public void onError(Throwable t) {
							log.error("Failure", t);
							pushDone.countDown();
							ret.setMessage(t.getMessage());
						}

						@Override
						public void onEvent(String event) {
						}
					}).withTag(tagName).toRegistry();

			pushDone.await();
			handle.close();
			return "ok".equals(ret.getMessage()) ? Result.getSuc() : ret;
		} catch (Exception e) {
			log.error("build失败", e);
			ret.setMessage(e.getMessage());
			return ret;
		}
	}

	/***
	 * 推送通过catalog,eg: pushImage("hammer","1.5-2","hammer:1");
	 * 
	 * @param image
	 *            要注册的image
	 * @param catalog
	 *            要注册的catalog
	 * @param tagName
	 *            注册库的tag
	 * @return
	 */
	public Result pushImageByCatalog(String image, String catalog, String tagName) {
		String repositoryName = IOUtil.mergeFolderAndFilePath(Conf.get("common.others.docker.registry"), catalog);
		return pushImage(image, repositoryName, tagName);
	}

}
